package com.igoal.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import org.compass.annotations.SearchableProperty;

@Entity
@Table(name="user_goal")
@AssociationOverrides({
	@AssociationOverride(name="pk.user", joinColumns=@JoinColumn(name="user_id")),
	@AssociationOverride(name="pk.goal", joinColumns=@JoinColumn(name="goal_id"))
})
public class UserGoal extends BaseObject implements Serializable, Audit, PrivacySupport {
	private static final long serialVersionUID = 1376224522731774291L;
	
	private UserGoalPk pk = new UserGoalPk();
	private Date createDate;
	private Date updateDate;
	private DataStatus status;		
	private GoalStatusEnum goalStatus;
	private Set<UserGoalEntry> entries = new HashSet<UserGoalEntry>();
	private Set<UserGoalDone> doneEntries = new HashSet<UserGoalDone>();
	private List<UserGoalPhase> phaseList = new ArrayList<UserGoalPhase>();
	private Integer percent;
	private Integer taskCount;
	private Date deadLine;
	private PrivacySetting privacy;
	private String value;
	
	@Transient
	public User getUser() {
		return pk.getUser();
	}

	public void setUser(User user) {
		this.pk.setUser(user);
	}

	@Transient
	public Goal getGoal() {
		return this.pk.getGoal();
	}

	public void setGoal(Goal goal) {
		this.pk.setGoal(goal);
	}

	public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
 
        UserGoal that = (UserGoal) o;
 
        if (getPk() != null ? !getPk().equals(that.getPk()) : that.getPk() != null) return false;
 
        return true;
    }
 
    public int hashCode() {
        return (getPk() != null ? getPk().hashCode() : 0);
    }


	@Override
	public String toString() {
		if(this.pk != null){
			return pk.getGoal().toString() + " of " + pk.getUser().toString();
		}
		return null;
	}

	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable=false, name="cdate")
	public Date getCreateDate() {
		return createDate;
	}

	@EmbeddedId
	public UserGoalPk getPk() {
		return pk;
	}

	public void setPk(UserGoalPk pk) {
		this.pk = pk;
	}
	
	@OneToMany
	@JoinColumns({
		@JoinColumn(name="user_id", referencedColumnName="user_id"),
		@JoinColumn(name="goal_id", referencedColumnName="goal_id")
	})
	public Set<UserGoalEntry> getEntries() {
		return entries;
	}

	public void setEntries(Set<UserGoalEntry> entries) {
		this.entries = entries;
	}

	@OneToMany
	@JoinColumns({
		@JoinColumn(name="user_id", referencedColumnName="user_id"),
		@JoinColumn(name="goal_id", referencedColumnName="goal_id")
	})
	public Set<UserGoalDone> getDoneEntries() {
		return doneEntries;
	}

	public void setDoneEntries(Set<UserGoalDone> doneEntries) {
		this.doneEntries = doneEntries;
	}
	
	@OneToMany
	@JoinColumns({
		@JoinColumn(name="user_id", referencedColumnName="user_id"),
		@JoinColumn(name="goal_id", referencedColumnName="goal_id")
	})
	public List<UserGoalPhase> getPhaseList() {
		return phaseList;
	}

	public void setPhaseList(List<UserGoalPhase> phaseList) {
		this.phaseList = phaseList;
	}

	@Enumerated(EnumType.STRING)
	@Column(nullable=false, name="goal_status")
	@SearchableProperty
	public GoalStatusEnum getGoalStatus() {
		return goalStatus;
	}

	public void setGoalStatus(GoalStatusEnum goalStatus) {
		this.goalStatus = goalStatus;
	}

	@Enumerated(EnumType.STRING)
	@Column(nullable=false, name="status")
	@SearchableProperty
	public DataStatus getStatus() {
		return status;
	}

	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable=false, name="mdate")
	public Date getUpdateDate() {
		return updateDate;
	}

	public void setCreateDate(Date date) {
		this.createDate = date;
	}

	public void setStatus(DataStatus dataStatus) {
		this.status = dataStatus;
	}

	public void setUpdateDate(Date date) {
		this.updateDate = date;
	}

	@Column(nullable=false, name="percent")
	public Integer getPercent() {
		return percent;
	}

	public void setPercent(Integer percent) {
		this.percent = percent;
	}
	
	@Column(nullable=false, name="num_task")
	public Integer getTaskCount() {
		return taskCount;
	}

	public void setTaskCount(Integer taskCount) {
		this.taskCount = taskCount;
	}
	
	@Column(name="dead_line", nullable=true)
	public Date getDeadLine() {
		return deadLine;
	}

	public void setDeadLine(Date deadLine) {
		this.deadLine = deadLine;
	}
	
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "privacy")
	public PrivacySetting getPrivacy() {
		return this.privacy;
	}

	public void setPrivacy(PrivacySetting privacy) {
		this.privacy = privacy;
	}
	
	@Column(name="value", nullable=true)
	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}
}
